package com.haiyou.common.util;

import com.haiyou.common.exception.BusinessException;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 *
 * @author root
 * @date 2019-03-09 19:01:19
 */
public class DateUtil {

    public static final String TIME_PATTERN2 = "HH:mm";
    public static final String TIME_PATTERN = "HH:mm:ss";
    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
    public static final String HOUR_PATTERN = "yyyy-MM-dd HH";
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String MONTH_PATTERN = "yyyy-MM";
    public static final String YEAR_PATTERN = "yyyy";
    public static final String YEAR_PATTERN2 = "yyyyMM";
    public static final String DATE_PATTERN2 = "yyyyMMdd";

    /**
     * 日期格式化
     *
     * @return 返回日期格式化后的字符串
     */
    public static String dateFormat() {
        return dateFormat(null, null);
    }

    public static Date strToDate(String date, String pattern) {
        SimpleDateFormat sDateFormat = new SimpleDateFormat(pattern);
        try {
            return sDateFormat.parse(date);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 日期格式化
     *
     * @param date    日期时间
     * @param pattern 日期格式
     * @return 返回日期格式化后的字符串
     */
    public static String dateFormat(Date date, String pattern) {
        if (date == null) {
            //默认当前时间
            date = new Date();
        }
        if (pattern == null) {
            // 默认日期格式化
            pattern = DATE_TIME_PATTERN;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    /**
     * 获取本周的开始时间
     *
     * @return
     */
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == 1) {
            dayOfWeek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayOfWeek);
        return getDayStartTime(cal.getTime());
    }

    /**
     * 获取某个日期的开始时间
     *
     * @param d
     * @return
     */
    public static Timestamp getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new Timestamp(calendar.getTimeInMillis());
    }

    public static Date getCurrentDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取本周的结束时间
     *
     * @return
     */
    public static Date getEndDayOfWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }

    /**
     * 获取某个日期的结束时间
     *
     * @param d
     * @return
     */
    public static Timestamp getDayEndTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new Timestamp(calendar.getTimeInMillis());
    }


    /**
     * 用当天的日期的long型字符数串减去昨天日期long型字符数串
     * 其中：
     * 86400000L，它的意思是说1天的时间=24小时 x 60分钟 x 60秒 x 1000毫秒 单位是L。
     *
     * @return
     */
    public static String getYesterdayByDate(int day) {
        //实例化当天的日期
        Date today = new Date();
        //用当天的日期减去昨天的日期
        Date yesterdayDate = new Date(today.getTime() - day * 86400000L);
        String yesterday = new SimpleDateFormat(DATE_TIME_PATTERN).format(yesterdayDate);
        return yesterday;
    }

    /**
     * @param incr 增长因子，单位为天
     * @return
     */
    public static String getDate(int incr) {
        Date today = new Date();
        Date yesterdayDate = new Date(today.getTime() + incr * 86400000L);
        String yesterday = new SimpleDateFormat(DATE_PATTERN).format(yesterdayDate);
        return yesterday;
    }

    public static List<String> getBetweenDate(String begin, String end) {
        List<String> betweenList = new ArrayList<>();
        if (begin.equals(end)) {
            betweenList.add(begin);
            return betweenList;
        }

        Date beginDate = strToDate(begin, DATE_PATTERN);
        Date endDate = strToDate(end, DATE_PATTERN);
        if (beginDate.getTime() > endDate.getTime()) {
            throw new BusinessException("开始日期不能大于结束日期");
        }

        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        try {
            //此处指定日期/时间解析是否不严格，在true是不严格，false时为严格
            format.setLenient(false);
            Calendar startDay = Calendar.getInstance();
            startDay.setTime(format.parse(begin));
            startDay.add(Calendar.DATE, -1);

            while (true) {
                startDay.add(Calendar.DATE, 1);
                Date newDate = startDay.getTime();
                String newEnd = format.format(newDate);
                betweenList.add(newEnd);
                if (end.equals(newEnd)) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return betweenList;
    }

    /**
     * 获取当月第一天
     *
     * @return
     */
    public static String monthOfFirstDay() {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        Calendar cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        return format.format(cale.getTime());
    }

    /**
     * 获取当月最后一天
     *
     * @return
     */
    public static String monthOfLastDay() {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        Calendar cale = cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        return format.format(cale.getTime());
    }

    /**
     * 两个日期之间的所有月份
     *
     * @param minDate
     * @param maxDate
     * @param interval 区间：1(minDate,maxDate],2=[minDate,maxDate),0=[minDate,maxDate]
     * @return
     */
    public static List<String> getMonthBetween(Date minDate, Date maxDate, int interval) {
        ArrayList<String> result = new ArrayList<>();

        if (maxDate.compareTo(minDate) == 0) {
            result.add(DateUtil.dateFormat(maxDate, DateUtil.MONTH_PATTERN));
        }

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(minDate);
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(maxDate);
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(dateFormat(curr.getTime(), MONTH_PATTERN));
            curr.add(Calendar.MONTH, 1);
        }
        if (interval == 1) {
            result.remove(0);
        } else if (interval == 2) {
            result.remove(result.size() - 1);
        }
        return result;
    }

    public static String getAddDate(String strDate) {
        return getAddDate(strDate, 1);
    }

    public static String getAddDate(String strDate, int amount) {
        Date date = strToDate(strDate, DATE_PATTERN);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, amount);
        return dateFormat(calendar.getTime(), DATE_PATTERN);
    }

    public static String getReduceDate(String strDate) {
        Date date = strToDate(strDate, DATE_PATTERN);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        return dateFormat(calendar.getTime(), DATE_PATTERN);
    }

    /**
     * 获取某个月的天数
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 遵循rfc3339标准格式，格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE
     */
    public static String wxDateTime(Date date) {
        return new DateTime(date == null ? new Date() : date, DateTimeZone.forTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))).toString();
    }

    public static String wxDateTime(String strDate) {
        DateTime dateTime = new DateTime(strDate);
        return dateTime.toString("yyyy-MM-dd HH:mm:ss");
    }

    public static Date wxDateTime2(String strDate) {
        return new DateTime(strDate).toDate();
    }

    /**
     * 获取上一个月
     *
     * @return
     */
    public static String getLastMonth(String dateTime) {
        SimpleDateFormat format = new SimpleDateFormat(YEAR_PATTERN2);
        Date date = new Date();
        if (StringUtils.isNotEmpty(dateTime)) {
            date = DateUtil.strToDate(dateTime, YEAR_PATTERN2);
        }
        Calendar calendar = Calendar.getInstance();
        // 设置为当前时间
        calendar.setTime(date);
        // 设置为上一个月
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        date = calendar.getTime();
        return format.format(date);

    }


    /**
     * 获取下一个月
     *
     * @return
     */
    public static String getNextMonth(String dateTime) {
        SimpleDateFormat format = new SimpleDateFormat(YEAR_PATTERN2);
        Date date = new Date();
        if (StringUtils.isNotEmpty(dateTime)) {
            date = DateUtil.strToDate(dateTime, YEAR_PATTERN2);
        }
        Calendar calendar = Calendar.getInstance();
        // 设置为当前时间
        calendar.setTime(date);
        // 设置为下一个月
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        date = calendar.getTime();
        return format.format(date);
    }

    public static boolean beforeDate(Date validDate) {
        String dateFormat = DateUtil.dateFormat(validDate, DateUtil.DATE_PATTERN);
        Date validTime = DateUtil.strToDate(dateFormat + " 23:59:59", DateUtil.DATE_TIME_PATTERN);
        if (validTime.before(new Date())) {
            return true;
        }
        return false;
    }

    public static boolean afterDate(Date validDate) {
        String dateFormat = DateUtil.dateFormat(validDate, DateUtil.DATE_PATTERN);
        Date validTime = DateUtil.strToDate(dateFormat + " 23:59:59", DateUtil.DATE_TIME_PATTERN);
        if (validTime.after(new Date())) {
            return true;
        }
        return false;
    }

    public static void checkDate(String str, String pattern) {
        SimpleDateFormat sd = new SimpleDateFormat(pattern);
        try {
            //此处指定日期/时间解析是否不严格，在true是不严格，false时为严格
            sd.setLenient(false);
            sd.parse(str);
        } catch (Exception e) {
            throw new BusinessException("日期格式错误");
        }
    }

    public static void main(String[] args) {

        System.out.println(getLastMonth(null));

        System.out.println(getNextMonth(null));

//        String minDate = "2020-01-03 12:30:45";
//        String maxDate = "2020-03-03 12:50:45";
//        List<String> list = getMonthBetween(strToDate(minDate, DateUtil.MONTH_PATTERN), strToDate(maxDate, DateUtil.MONTH_PATTERN), 1);
//        System.out.println(list);
//
//        int day = list.stream().mapToInt(str -> DateUtil.getDaysOfMonth(DateUtil.strToDate(str, DateUtil.MONTH_PATTERN))).sum();
//
//
//        System.out.println(day);


//        String dateString = dateFormat(new Date(), DATE_PATTERN);
//        System.out.println(dateString);
//
//        List<String> list = getBetweenDate("2019-04-27", "2019-05-01");
//        System.out.println(list);
//        Map<String, Integer> map = new HashMap<>();
//        for (String date : list) {
//            map.put(date, 1);
//        }
//        System.out.println(map);

//        System.out.println(dateFormat(new Date(), DATE_PATTERN));
//        Date begin = DateUtil.getBeginDayOfWeek();
//        Date end = DateUtil.getEndDayOfWeek();
//        System.out.println("begin==>" + begin + ",end=" + end);
    }
}